package com.renjianbo.project.common.util;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class CodeGeneratorUtil {

    /**
     * 自定义配置文件
     */
    public static List<FileOutConfig> customFileOutConfig(String tableName, String moduleName, String srcPath, String projectPackagePath, String resourcesPath) {
        List<FileOutConfig> focList = new ArrayList<>();

        focList.add(new FileOutConfig("/templates/controller.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {

                return srcPath + (projectPackagePath).replaceAll("\\.", "/") + "/controller/" + tableInfo.getEntityName() + "Controller" + StringPool.DOT_JAVA;
            }
        });

        focList.add(new FileOutConfig("/templates/mapper.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return srcPath + (projectPackagePath).replaceAll("\\.", "/") + "/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_JAVA;
            }
        });

        focList.add(new FileOutConfig("/templates/service.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return srcPath + (projectPackagePath).replaceAll("\\.", "/") + "/service/" + tableInfo.getEntityName() + "Service" + StringPool.DOT_JAVA;
            }
        });

        focList.add(new FileOutConfig("/templates/serviceImpl.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return srcPath + (projectPackagePath).replaceAll("\\.", "/") + "/service/impl/" + tableInfo.getEntityName() + "ServiceImpl" + StringPool.DOT_JAVA;
            }
        });

        focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return resourcesPath + "mapper\\" + moduleName + "\\" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });

        focList.add(new FileOutConfig("/templates/entity.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return srcPath + (projectPackagePath).replaceAll("\\.", "/") + "/model/" + tableName + "/" + tableInfo.getEntityName() + StringPool.DOT_JAVA;
            }
        });

        focList.add(new FileOutConfig("/templates/modelDTO.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return srcPath + (projectPackagePath).replaceAll("\\.", "/") + "/model/" + tableName + "/" + tableInfo.getEntityName() + "DTO" + StringPool.DOT_JAVA;
            }
        });

        focList.add(new FileOutConfig("/templates/modelVO.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                tableInfo.getFields().removeIf(item ->
                        item.getColumnName().equals("IS_DELETE")
                );

                return srcPath + (projectPackagePath).replaceAll("\\.", "/") + "/model/" + tableName.toLowerCase() + "/" + tableInfo.getEntityName() + "VO" + StringPool.DOT_JAVA;
            }
        });

        focList.add(new FileOutConfig("/templates/modelSearchReq.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {

                return srcPath + (projectPackagePath).replaceAll("\\.", "/") + "/model/" + tableName.toLowerCase() + "/" + tableInfo.getEntityName() + "SearchReq" + StringPool.DOT_JAVA;
            }
        });

        focList.add(new FileOutConfig("/templates/modelUpdateReq.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                //  字段长度限制
                valueRange(tableInfo.getFields());

                return srcPath + (projectPackagePath).replaceAll("\\.", "/") + "/model/" + tableName.toLowerCase() + "/" + tableInfo.getEntityName() + "UpdateReq" + StringPool.DOT_JAVA;
            }
        });

        focList.add(new FileOutConfig("/templates/modelAddReq.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                //  字段长度限制
                valueRange(tableInfo.getFields());

                return srcPath + (projectPackagePath).replaceAll("\\.", "/") + "/model/" + tableName.toLowerCase() + "/" + tableInfo.getEntityName() + "AddReq" + StringPool.DOT_JAVA;
            }
        });

        return focList;
    }

    /**
     * 字段长度限制
     */
    public static void valueRange(List<TableField> tableFieldList){
        for (TableField tableField : tableFieldList) {
            String integerMin = null;    //  整数最小值
            String integerMax = null;    //  整数最大值
            String numericPrecision = null;   //   小数的整数部分位数
            String numericScale = null;   //   小数的小数部分位数
            String decimalMin = null;   //  Decimal最小值
            String decimalMax = null;   //  Decimal最大值
            Short character_length = null; //  字符长度

            Map<String, Object> customMap = tableField.getCustomMap();

            if(tableField.getType().startsWith("tinyint")){
                integerMin = "-128";
                integerMax = "127";
                customMap.put("integerMin",  new BigDecimal(integerMin).toPlainString());
                customMap.put("integerMax",  new BigDecimal(integerMax).toPlainString());
            }
            else if(tableField.getType().startsWith("smallint")){
                integerMin = "-32768";
                integerMax = "32768";
                customMap.put("integerMin",  new BigDecimal(integerMin).toPlainString());
                customMap.put("integerMax",  new BigDecimal(integerMax).toPlainString());
            }
            else if(tableField.getType().startsWith("mediumint")){
                integerMin = "-8388607";
                integerMax = "8388607";
                customMap.put("integerMin",  new BigDecimal(integerMin).toPlainString());
                customMap.put("integerMax",  new BigDecimal(integerMax).toPlainString());
            }
            else if(tableField.getType().startsWith("int") || tableField.getType().startsWith("integer")){
                integerMin = "-2147483647";
                integerMax = "2147483647";
                customMap.put("integerMin",  new BigDecimal(integerMin).toPlainString());
                customMap.put("integerMax",  new BigDecimal(integerMax).toPlainString());
            }
            else if(tableField.getType().startsWith("bigint")){
                integerMin = "-9223372036854775807";
                integerMax = "9223372036854775807";
                customMap.put("integerMin",  new BigDecimal(integerMin).toPlainString() + "L");
                customMap.put("integerMax",  new BigDecimal(integerMax).toPlainString() + "L");
            }
            else if(tableField.getType().startsWith("float") || tableField.getType().startsWith("double") ){
                if(getBracketContent(tableField.getType()).length > 0){
                    //  整数位数
                    numericPrecision = getBracketContent(tableField.getType())[0].split(",")[0];
                    //  小数位数
                    numericScale = getBracketContent(tableField.getType())[0].split(",")[1];

                    customMap.put("numericPrecision",  new BigDecimal(numericPrecision).toPlainString());
                    customMap.put("numericScale",  new BigDecimal(numericScale).toPlainString());
                }
            }
            else if(tableField.getType().startsWith("decimal")){
                if(getBracketContent(tableField.getType()).length > 0){
                    //  精度
                    long  numeric_precision = Short.parseShort(getBracketContent(tableField.getType())[0].split(",")[0]);
                    //  小数长度
                    long numeric_scale = Short.parseShort(getBracketContent(tableField.getType())[0].split(",")[1]);

                    /* 拼接最大值*/
                    //  整数部分
                    double integerPart   = (Math.pow(10, numeric_precision - numeric_scale) - 1);
                    //  小数部分
                    double decimalPart =(Math.pow(10, numeric_scale) - 1);

                    decimalMin = "-" + integerPart + "." + decimalPart;
                    decimalMax = integerPart + "." + decimalPart;
                    customMap.put("decimalMin",  new BigDecimal(decimalMin).toPlainString());
                    customMap.put("decimalMax",  new BigDecimal(decimalMax).toPlainString());
                }
            }

            //  非数字类型
            else {
                if(getBracketContent(tableField.getType()).length > 0){
                    character_length = Short.parseShort(getBracketContent(tableField.getType())[0]);
                    customMap.put("character_length", new BigDecimal(character_length).toPlainString());
                }
            }

            log.info("{}:integerMin：{}", tableField.getType(), integerMin);
            log.info("{}:integerMax：{}", tableField.getType(), integerMax);
            log.info("{}:numericPrecision：{}", tableField.getType(), numericPrecision);
            log.info("{}:numericScale：{}", tableField.getType(), numericScale);
            log.info("{}:decimalMin：{}", tableField.getType(), decimalMin);
            log.info("{}:decimalMax：{}", tableField.getType(), decimalMax);
            log.info("{}：character_length：{}", tableField.getType(), character_length);
        }
    }

    /**
     *  获取指定字符串中括号内的内容，返回字符串数组
     */
    public static String[] getBracketContent(String content){
        String [] arr = new String[0];
        Pattern p = Pattern.compile("(?<=\\()[^\\)]+");
        Matcher m = p.matcher(content);
        while(m.find()){
            arr = Arrays.copyOf(arr,arr.length+1);
            arr[arr.length-1]=m.group();
        }
        return arr;
    }

    public static void main(String[] args) {
        log.info(getBracketContent("bigint(13)")[0]);
        log.info(getBracketContent("double(13,2)")[0]);

    }


}
